/**
 * 订阅事件和发布事件，类似nodejs EventEmitter
 * @export
 * @class EventManager
 */
export default class EventManager {
  constructor() {
    this.listenerList = {}
  }

  /**
   * 订阅事件
   * @param {*} type 事件名
   * @param {*} scope 作用域
   * @param {*} callback 回调
   * @param {*} [params=[]] 回调参数
   * @memberof EventManager
   */
  on(type, scope, callback, params = []) {
    // 订阅的放到数组记录
    const listenerParams = { callback: callback, scope: scope, params: params, isOnce: false }
    this.addListener(type, listenerParams)
  }

  /**
   * 订阅事件-回调只执行一次
   * @param {*} type
   * @param {*} scope 作用域
   * @param {*} callback
   * @param {*} [params=[]] 回调参数
   * @memberof EventManager
   */
  once(type, scope, callback, params = []) {
    // 订阅的放到数组记录
    const listenerParams = { callback: callback, scope: scope, params: params, isOnce: true }
    this.addListener(type, listenerParams)
  }

  /**
   * 发布事件
   * @param {*} type
   * @param {array} [params=[]] 附加到回调的参数
   * @memberof EventManager
   */
  emit(type, params = []) {
    // 订阅的放到数组记录
    if (!(params instanceof Array)) {
      console.error('传参出错params应该是一个数组')
      return
    }
    let listenerParamsArr = this.listenerList[type]
    // console.log('111发布事件', listenerParamsArr)
    if (listenerParamsArr) {
      let tempList = []
      for (const listenerParams of listenerParamsArr) {
        // console.log('发布事件', listenerParams)
        let scope = listenerParams['scope']
        // on传的参数
        let toOnParams = listenerParams['params']
        // 作用域
        !scope && (scope = this)

        // on的时候传的参数
        let allParams = []
        if (toOnParams && toOnParams instanceof Array) {
          allParams = allParams.concat(toOnParams)
        }

        // 附加参数
        if (params instanceof Array) {
          allParams = allParams.concat(params)
        }

        listenerParams['callback'].apply(scope, allParams) // [param,...]

        if (!listenerParams['isOnce']) {
          tempList.push(listenerParams)
        }
      }
      this.listenerList[type] = tempList
    }
  }

  /**
   * 获取指定事件的监听器数组列表
   * @param {*} type 事件名
   * @return {array | undefined} 返回列表
   * @memberof EventManager
   */
  getListener(type) {
    let listenerList = this.getListenerList()
    return listenerList[type]
  }

  /**
   * 获取全部事件的全部监听者的列表
   * @return {*}
   * @memberof EventManager
   */
  getListenerList() {
    let listenerList = this.listenerList || {}
    return listenerList
  }

  /**
   * 获取已经监听的事件名列表
   * @return {array} 事件名数组
   * @memberof EventManager
   */
  getEventNames() {
    let listenerList = this.getListenerList()
    let eventNames = []
    for (const type in listenerList) {
      eventNames.push(type)
    }
    return eventNames
  }

  /**
   * 添加到事件等待处理触发列表
   * @param {*} type
   * @param {*} [listenerParams={ callback: null, scope: this, params: null, isOnce: false }] 触发事件的参数
   * @memberof EventManager
   */
  addListener(type, listenerParams = { callback: null, scope: this, params: null, isOnce: false }) {
    if (!listenerParams) {
      console.error('传参出错，确认是否漏传了？')
      return
    }

    let params = listenerParams['params']
    let callback = listenerParams['callback']

    // 订阅的放到数组记录
    if (!type || !callback) {
      console.error('传参出错，确认是否漏传了？')
      return
    }

    // 订阅的放到数组记录
    if (!(params instanceof Array)) {
      console.error('传参出错params应该是一个数组')
      return
    }

    if (typeof callback !== 'function') {
      console.error('回调应为一个函数')
      return
    }

    !this.listenerList[type] && (this.listenerList[type] = [])
    if (this.listenerList[type].indexOf(listenerParams) == -1) {
      this.listenerList[type].push(listenerParams)
    } else {
      console.warn('该事件已经被添加过了')
    }
  }

  /**
   * 清除所有订阅
   * @param {*} [type=null] 事件名， 如果指定事件则移除该事件的所有监听器，如果不传则移除所有事件的所有监听器，并注销事件
   * @memberof EventManager
   */
  offAll(type = null) {
    if (type) {
      let listenerParamsArr = this.listenerList && this.listenerList[type]
      if (listenerParamsArr) {
        delete this.listenerList[type]
      }
    } else {
      this.listenerList = {}
    }
  }

  /**
   * 清除对应的订阅
   * @param {*} type 事件名
   * @param {*} removeCallback 监听器的回调函数
   * @memberof EventManager
   */
  off(type, removeCallback) {
    let listenerParamsArr = this.listenerList[type]
    let tempList = []
    if (listenerParamsArr) {
      if (typeof removeCallback === 'function') {
        for (const listenerParams of listenerParamsArr) {
          let callback = listenerParams['callback']
          if (removeCallback !== callback) {
            tempList.push(listenerParams)
          }
        }
        this.listenerList[type] = tempList
      } else {
        console.error('参数应该为一个函数')
      }
    }
  }
}
